#include "stdafx.h"
#include "roles/enemy/enemymgr.h"
#include "../gamemgr.h"
#include "../gamewrapper.h"
#include "./enemymodepage.h"

#define WAIT_TIME 1.5

#define LEVEL_POS Point(65, 97)
#define LEVEL_COLOR Color(0, 0, 0)
#define LEVEL_NUM_POS Point(70, 97)
#define LEVEL_NUM_COLOR Color(255, 0, 0)

#define LEFT_POS Point(65, 94.5)
#define LEFT_COLOR Color(0, 0, 0)
#define LEFT_NUM_POS Point(72.3, 94.5)
#define LEFT_NUM_COLOR Color(255, 0, 0)

EnemyModePage::EnemyModePage(string resultBkg, Point resultPos, string strAIDir)
: PlayerModePage(resultBkg, resultPos, strAIDir)
, m_level(0)
, m_enemyleft(0)
, m_textLevel("level:", LEVEL_POS, GameMgr::GetInstance().GetStageDepth(), 9, LEVEL_COLOR)
, m_pTextLevelNum(NULL)
, m_textLeft("monsters:", LEFT_POS, GameMgr::GetInstance().GetStageDepth(), 9, LEFT_COLOR)
, m_pTextLeftNum(NULL)
{
	m_pTextLevelNum = new TextObj("0", LEVEL_NUM_POS, GameMgr::GetInstance().GetStageDepth(), 9, LEVEL_NUM_COLOR);
	m_pTextLeftNum = new TextObj("0", LEFT_NUM_POS, GameMgr::GetInstance().GetStageDepth(), 9, LEFT_NUM_COLOR);

	for (size_t i = 0; i < MAX_ENEMY_COUNT; ++i)
	{
		EnemyMgr::GetInstance().GetEnemy(i)->OnDestroy += EventObject<OnEnemyDestroyFunc>(this, &EnemyModePage::OnEnemyDestroy);
	}
}

EnemyModePage::~EnemyModePage()
{
	for (size_t i = 0; i < MAX_ENEMY_COUNT; ++i)
	{
		EnemyMgr::GetInstance().GetEnemy(i)->OnDestroy -= EventObject<OnEnemyDestroyFunc>(this, &EnemyModePage::OnEnemyDestroy);
	}

	EnemyMgr::GetInstance().Stop();

	delete m_pTextLevelNum;
	m_pTextLevelNum = NULL;

	delete m_pTextLeftNum;
	m_pTextLeftNum = NULL;
}

void EnemyModePage::OnReadyEnd()
{
	PlayerModePage::OnReadyEnd();
	StatMgr::GetInstance().SetMinPlayerCount(0);

	LevelUp();

	EnemyMgr::GetInstance().Start();
}

void EnemyModePage::LevelUp()
{
	m_level++;
	m_enemyleft = (int)powf(2, m_level);

	ChangeText();
	ResetEnemies();

	GameWrapper::UpdateEnemiesTbl(m_enemyleft);
}

void EnemyModePage::ChangeText()
{
	delete m_pTextLevelNum;
	delete m_pTextLeftNum;

	char buf[5];
	sprintf_s(buf, 5, "%d", m_level);
	m_pTextLevelNum = new TextObj(buf, LEVEL_NUM_POS, GameMgr::GetInstance().GetStageDepth(), 9, LEVEL_NUM_COLOR);

	sprintf_s(buf, 5, "%d", m_enemyleft);
	m_pTextLeftNum = new TextObj(buf, LEFT_NUM_POS, GameMgr::GetInstance().GetStageDepth(), 9, LEFT_NUM_COLOR);
}

void EnemyModePage::ResetEnemies()
{
	int settedCount = 0;

	Point* enemiesPos = new Point[m_enemyleft];
	float* enemiesAngle = new float[m_enemyleft];

	srand(time(0));
	for (int i = 0; i < m_enemyleft; ++i)
	{
		int angle = rand() % 360;
		enemiesPos[i] = GetEnemyPosByAngle(angle);
		enemiesAngle[i] = angle - 180;
	}

	EnemyMgr::GetInstance().ResetEnemies(m_enemyleft, enemiesPos, enemiesAngle);
}

Point EnemyModePage::GetEnemyPosByAngle(float angle)
{
	Size stageSize = GameMgr::GetInstance().GetStageSize();

	if (angle >= 315 || angle <= 45)
	{
		//right
		return Point(stageSize.cx, stageSize.cy / 2 + stageSize.cx * tanf(MathUtils::AngleToRadian(angle)) / 2);
	}
	else if (angle > 45 && angle <= 135)
	{
		//top
		return Point(stageSize.cx / 2 - stageSize.cy * tanf(MathUtils::AngleToRadian(angle - 90)) / 2, stageSize.cy);
	}
	else if (angle > 135 && angle <= 225)
	{
		//left
		return Point(0, stageSize.cy / 2 + stageSize.cx * tanf(MathUtils::AngleToRadian(angle - 180)) / 2);
	}
	else
	{
		//bottom
		return Point(stageSize.cx / 2 + stageSize.cy * tanf(MathUtils::AngleToRadian(angle - 270)) / 2, 0);
	}
}

void EnemyModePage::OnEnemyDestroy(Enemy* pEnemy)
{
	m_enemyleft--;

	delete m_pTextLeftNum;
	char buf[5];
	sprintf_s(buf, 5, "%d", m_enemyleft);
	m_pTextLeftNum = new TextObj(buf, LEFT_NUM_POS, GameMgr::GetInstance().GetStageDepth(), 9, LEFT_NUM_COLOR);

	if (m_enemyleft == 0)
	{
		m_waitTime = 0;
		RenderMgr::GetInstance().OnAfterRender += EventObject<OnAfterRenderFunc>(this, &EnemyModePage::OnAfterRender);
	}
}

void EnemyModePage::OnAfterRender(float differTime)
{
	m_waitTime += differTime;

	if (m_waitTime >= WAIT_TIME)
	{
		RenderMgr::GetInstance().OnAfterRender -= EventObject<OnAfterRenderFunc>(this, &EnemyModePage::OnAfterRender);
		LevelUp();
	}
}

void EnemyModePage::OnStatEnd(int playerCount, StatData* pStatDatas)
{
	m_pStageObj->ShutDownStage();
	m_pResultPage->SetVisible(true);

	//Show Result Text
	for (int i = 0; i < playerCount; ++i)
	{
		StatData* pStatData = pStatDatas + i;

		//player name
		TextObj* pTextNameBkg = new TextObj(pStatData->strName, Point(3.2, 57.8 - 10.5 * i), GameMgr::GetInstance().GetStageDepth() - 1, 12, Color(255, 255, 255));
		TextObj* pTextName = new TextObj(pStatData->strName, Point(3, 58 - 10.5 * i), GameMgr::GetInstance().GetStageDepth(), 12, pStatData->color);
		m_textlist.push_back(pTextNameBkg);
		m_textlist.push_back(pTextName);

		//player bullets count
		TextObj* pTextBulletsBkg = new TextObj(StrUtils::IntToString(pStatData->bulletCount), Point(19.6, 57.8 - 10.5 * i), GameMgr::GetInstance().GetStageDepth() - 1, 12, Color(255, 255, 255));
		TextObj* pTextBullets = new TextObj(StrUtils::IntToString(pStatData->bulletCount), Point(19.5, 58 - 10.5 * i), GameMgr::GetInstance().GetStageDepth(), 12, pStatData->color);
		m_textlist.push_back(pTextBulletsBkg);
		m_textlist.push_back(pTextBullets);

		//hitted_player name
		TextObj* pTextHittedNameBkg = new TextObj(pStatData->strName, Point(28.6 + 12 * i, 66.8), GameMgr::GetInstance().GetStageDepth() - 1, 12, Color(255, 255, 255));
		TextObj* pTextHittedName = new TextObj(pStatData->strName, Point(28.5 + 12 * i, 67), GameMgr::GetInstance().GetStageDepth(), 12, pStatData->color);
		m_textlist.push_back(pTextHittedNameBkg);
		m_textlist.push_back(pTextHittedName);

		int hittedcount = 0;

		//hitted bullets count
		for (int y = 0; y < playerCount; ++y)
		{
			//hitted_player name
			TextObj* pTextHittedBulletsBkg = new TextObj(StrUtils::IntToString(pStatData->hittedCount[y]), Point(30.2 + 12 * y, 57.8 - 10.5 * i), GameMgr::GetInstance().GetStageDepth() - 1, 12, Color(255, 255, 255));
			TextObj* pTextHittedBullets = new TextObj(StrUtils::IntToString(pStatData->hittedCount[y]), Point(30.1 + 12 * y, 58 - 10.5 * i), GameMgr::GetInstance().GetStageDepth(), 12, pStatData->color);
			m_textlist.push_back(pTextHittedBulletsBkg);
			m_textlist.push_back(pTextHittedBullets);
		}

		//hitted enemy bullets count
		TextObj* pTextEnemyBulletsBkg = new TextObj(StrUtils::IntToString(pStatData->hittedCount[4]), Point(80.6, 57.8 - 10.5 * i), GameMgr::GetInstance().GetStageDepth() - 1, 12, Color(255, 255, 255));
		TextObj* pTextEnemyBullets = new TextObj(StrUtils::IntToString(pStatData->hittedCount[4]), Point(80.5, 58 - 10.5 * i), GameMgr::GetInstance().GetStageDepth(), 12, pStatData->color);
		m_textlist.push_back(pTextEnemyBulletsBkg);
		m_textlist.push_back(pTextEnemyBullets);	

		hittedcount = pStatData->hittedCount[4];

		//hitted percent
		float percent = pStatData->bulletCount == 0 ? 0 : hittedcount / (float)pStatData->bulletCount;
		static char percentbuf[256];
		sprintf_s(percentbuf, 256, "%.2f%%", percent * 100);

		TextObj* pTextPercentBkg = new TextObj(percentbuf, Point(90.6, 57.8 - 10.5 * i), GameMgr::GetInstance().GetStageDepth() - 1, 12, Color(255, 255, 255));
		TextObj* pTextPercent = new TextObj(percentbuf, Point(90.5, 58 - 10.5 * i), GameMgr::GetInstance().GetStageDepth(), 12, pStatData->color);
		m_textlist.push_back(pTextPercentBkg);
		m_textlist.push_back(pTextPercent);
	}
}